#include "tcp_receiver.hh"
#include <iostream>

// Dummy implementation of a TCP receiver

// For Lab 2, please replace with a real implementation that passes the
// automated checks run by `make check_lab2`.

using namespace std;


void TCPReceiver::segment_received(const TCPSegment &seg) {
    const TCPHeader &header = seg.header();
    const Buffer &payload = seg.payload();
    WrappingInt32 wrapping_seqno(header.seqno);

    //const size_t len = seg.length_in_sequence_space();

    if(header.syn){
        if(_isn == nullopt){
            _isn = wrapping_seqno;
            wrapping_seqno = wrapping_seqno + 1;
            _syn = true;
        }else
            return;
    }else if(_isn == nullopt)
        return;

    // 将seqno，转成absolute seqno，再减1，得到stream index
    uint64_t &&abs_seqno = unwrap(wrapping_seqno, _isn.value(), stream_out().bytes_written()); // + stream_out().buffer_size()
    uint64_t &&stream_index = abs_seqno - (abs_seqno > 0);
    string &&payload_str = payload.copy();
    // 没有syn，但是起始字节序号占用了syn的0号，要把它削掉
    if(!header.syn && abs_seqno == 0 && not payload_str.empty()){
        payload_str.erase(payload_str.begin());
    }

    if(header.fin)
        _fin = header.fin;

    _reassembler.push_substring(payload_str, stream_index, _fin);
}

inline size_t TCPReceiver::next_index() const {
    return stream_out().bytes_written();
}

optional<WrappingInt32> TCPReceiver::ackno() const {
    if(_isn == nullopt)
        return nullopt;

    uint64_t &&seqno = (next_index() + _syn + stream_out().input_ended() + _isn.value().raw_value()) % (uint64_t(1) << 32);
    return WrappingInt32(static_cast<uint32_t>(seqno));
}

size_t TCPReceiver::window_size() const {
    return _capacity - stream_out().buffer_size();
}

bool TCPReceiver::is_finished() const { return _reassembler._total_bytes == next_index(); }
